package cn.imokay.config;

import cn.imokay.entities.Pet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * proxyBeanMethods的作用:
 * 如果被@Bean的方法,项目中其它地方没有主动调用,推荐配置为false,spring将不会对其代理,提升项目启动的速度
 */
@Configuration(proxyBeanMethods = false)
public class WebConfig {


    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer(){

            //UrlPathHelper.removeSemicolonContent默认是true,
            // 表示去掉路径中带分号后面的全部内容,所以不支持矩阵变量,需要手动配置
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }

            //自定义转换器,将指定格式的String转为指定的entities
            @Override
            public void addFormatters(FormatterRegistry registry) {
                registry.addConverter(new Converter<String, Pet>() {

                    @Override
                    public Pet convert(String s) {
                        String[] split = s.split(",");

                        return new Pet(split[0],split[1],split[2]);
                    }
                });
            }

            //增加自定义内容协商转换器,自定义数据格式
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                HttpMessageConverter myHttpMessageConverter = new HttpMessageConverter() {

                    /**
                     * 能操作application/x-imokay:属性1#属性2#
                     * @return
                     */
                    @Override
                    public List<MediaType> getSupportedMediaTypes() {

                        return MediaType.parseMediaTypes("application/x-imokay");
                    }

                    @Override
                    public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
                        return null;
                    }

                    /**
                     * 自定义数据协议写出
                     * @param o
                     * @param contentType
                     * @param outputMessage
                     * @throws IOException
                     * @throws HttpMessageNotWritableException
                     */
                    @Override
                    public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
                        Pet pet = (Pet)o;
                        String data = pet.getAge()+"#"+pet.getBirth()+"#"+pet.getName();
                        outputMessage.getBody().write(data.getBytes());
                    }

                    @Override
                    public boolean canWrite(Class clazz, MediaType mediaType) {
                        return clazz.isAssignableFrom(Pet.class);
                    }

                    @Override
                    public boolean canRead(Class clazz, MediaType mediaType) {
                        return false;
                    }
                };
                converters.add(myHttpMessageConverter);
            }

            /**
             * 自定义内容协商
             * @param configurer
             */
           @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                HashMap<String, MediaType> mediaTypes = new HashMap<>();
                mediaTypes.put("imokay",MediaType.parseMediaType("application/x-imokay"));
                mediaTypes.put("json",MediaType.APPLICATION_JSON);
                mediaTypes.put("xml",MediaType.APPLICATION_XML);

                ParameterContentNegotiationStrategy parameterContentNegotiationStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
               parameterContentNegotiationStrategy.setParameterName("formatter");//此处不设置的话,会覆盖配置文件中的自定义name为默认

               //不增加头内容协商的话,默认的会被覆盖,导致头部协商不可用
               HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy();
               configurer.strategies(Arrays.asList(parameterContentNegotiationStrategy,headerContentNegotiationStrategy));


            }
        };

    }
}
